/******ARCHIVO CABECERA DE NUESTRO CODIGO DE TABLA HASH*****/

//LIBRERIAS

#include <ctype.h>
#include "LAHAROT01ef.h"


#ifndef __LAHAROT02ef_H_

//MACROS

#define __LAHAROT02ef_H_

//VARIABLES GLOBALES

FILE *archConfig, *archEntrada, *archSalida, *archCatalogo;
char nombreArchCatalogo[MAX_LINEA], nombreArchEntrada[MAX_LINEA];
char nombreArchSalida[MAX_LINEA], camposLlaveEntrada[MAX_LINEA];
char camposLlaveCatalogo[MAX_LINEA], camposCalifEntrada[MAX_LINEA];
char camposCalifCatalogo[MAX_LINEA], camposRazonDesc[3];
char separador, fecha_proceso[7], filtroAreas[MAX_LINEA];
TablaHS *new_TablaHS();
TablaHS **TABLAHASH;
long int contcoli, HASH_SIZE, no_llamadas, num_intentos, campoFiltroAreas;



TablaHS *new_TablaHS(){

    TablaHS *aux;
    aux = (TablaHS *)malloc(sizeof(TablaHS));
    int i;

    if (aux == NULL) // No hay mas memoria disponible
    {
	printf("\n No hay mas memoria disponible");
	   	 cleanupHash(99); 
	         exit(1);
    }
    for (i=0; i<14; i++)
          aux->razonDescon[i]=0;

    aux->razonDesc[0]='\0';
    aux->sig = NULL;
    aux->contLlam = 0;
    return aux;
}


//void addToHash(char *Clave, double Calif, char *razonDescon, long int intentos){
void addToHash(char *Clave, float Calif, char *razonDescon, long int intentos){

     long int modulo, i;
   
     modulo = calculaIndice_rot_hash(Clave);
     TablaHS *aux = getkey(Clave);

     if (aux == NULL)
     {
        aux = new_TablaHS();

        //se crea Clave
        aux->Clave=(char *)malloc(sizeof(char)*(strlen(Clave)+1));
        strcpy(aux->Clave, Clave);
        aux->Clave[strlen(aux->Clave)]='\0';

        //se crea Calif
        aux->Calif=Calif;
        
        //se crea razon
        strcpy(aux->razonDesc,razonDescon);
        aux->razonDesc[2]='\0';
        aux->contLlam+=intentos;
        //printf("->Calif:%f\n",Calif);
        //printf("->RazonDes:%s\n",aux->razonDesc);
        aux->razonDescon[selectRadex(Calif,aux->razonDesc)]+=intentos;
       

        if (TABLAHASH[modulo] == NULL)
             TABLAHASH[modulo]=aux;
        else
	     addToList(aux, TABLAHASH[modulo]);
	
     }
     else
     {
	 //printf("\nClave %s  Existente reescribiendo Contenido %s con el nuevo valor %s",aux->Clave, Calif, aux->Calif);
         //i=selectRadex(aux->Calif, razonDescon);
         i=selectRadex(Calif, razonDescon);
         aux->razonDescon[i]+=intentos;
         aux->contLlam+=intentos;
         aux->Calif+=Calif;
         //printf("\nEscribiendo nuevo contenido en segundos %ld y en formato: %s ",total, aux->Calif);
         //printf(" con %d llamadas a esta clave\n", aux->contLlam);
         /*printf("\nIntentos: ");
         for (i=0; i<14; i++)
              printf("%ld,", aux->razonDescon[i]);
         */
     } 
}


//FUNCION QUE LIMPIA LA TABLA HASH

void clearHash(){

    int i=0;

    for (i=0; i < HASH_SIZE; i++)
    {
        TABLAHASH[i] = NULL;
    }
}


//FUNCION QUE NOS AGREGA EN LA LISTA ELEMENTOS POR ENCADENAMIENTO SEPARADO DADA UNA COLISION

void addToList(TablaHS *tablaHS, TablaHS *indice){

    TablaHS *aux = indice;
    int isInCiclo=TRUE;

    contcoli++;
    while (isInCiclo)
    {
       //printf("\n C O L I S I O N !!!!!  El indice ya estaba ocupado por 1 o mas elementos ");

       if (aux->sig == NULL)
       {
	   aux->sig=tablaHS;
	   //printf("\nSe inserto el elemento");
	   isInCiclo=FALSE;
       }
       else
           aux = aux->sig;
    }
}


//FUNCION QUE NOS BUSCA LA CLAVE

TablaHS *getkey(char *key){

    long int modulo;

    //printf("\nBuscando ClaveLADA no. %s ......", key);
    modulo = calculaIndice_rot_hash(key);
    //printf("\nModulo en la busqueda %ld  ", modulo);
    return findInList(TABLAHASH[modulo], key);
}


//FUNCION QUE NOS HACE EL CALCULO DE LA POSICION QUE SE LE VA A ASIGNAR A CADA CLAVE

long int calculaIndice_rot_hash(char *key){

    unsigned long int h = 0;
    unsigned long int i;

    for (i=0; i < strlen(key); i++)
	 h = (h << 4 ) ^ (h >> 28 ) ^ key[i];

    return (h % HASH_SIZE);
}


//FUNCION QUE NOS BUSCA CLAVES DENTRO DE LA LISTA

TablaHS *findInList(TablaHS *indice, char *key){

   if (indice != NULL)
   {
       //printf("\nComparando indice->Clave = %s con key = %s", indice->Clave, key);

       if (strcmp(indice->Clave, key) == 0)
       {
	    //printf("\nClave encontrada indice->Clave = %s y key = %s", indice->Clave, key);
		       return indice;
       }

       else
	    return findInList(indice->sig, key);
   }
   else
	return NULL;
}     


//FUNCION PARA LA APERTURA DEL ARCHIVO DE CONFIGURACION

int abreArchivoConfiguracion(char *nomArchConfiguracion){

    if((archConfig = fopen(nomArchConfiguracion,"r")) == NULL)
    {
	printf(" !>\n Error: El archivo: %s no existe o no se encuentra \n\n",nomArchConfiguracion);
	       return FALSE;
    }

    return TRUE;
}


//FUNCION PARA LA APERTURA DE LOS ARCHIVOS


int abreArchivos(char *nomArchEntrada, char *nomArchCatalogo, char *nomArchSalida){

     if((archEntrada = fopen(nomArchEntrada, "r")) == NULL && archEntrada != NULL)
     {
	 printf(" !>\n Error: El archivo: %s no existe o no se encuentra \n\n", nomArchEntrada);
	          return FALSE;
     }

     if((archCatalogo = fopen(nomArchCatalogo, "r")) == NULL && archCatalogo != NULL)
     {
	 fclose(archEntrada);
	 printf(" !>\n Error: El archivo: %s no puede abrirse para lectura \n\n", nomArchCatalogo);
		  return FALSE;
     }

     if((archSalida = fopen(nomArchSalida, "w")) == NULL && archSalida != NULL)
     {
	 fclose(archEntrada);
	 fclose(archCatalogo);
	 printf(" !>\n Error: El archivo: %s no puede abrirse para escritura \n\n", nomArchSalida); 
		  return FALSE;
     }

     return TRUE;
}




//FUNCION QUE NOS CARGA EL CATALOGO A  MEMORIA

int cargaCatalogo(){

    fflush(stdin);
    fflush(stdout);
    //TablaHS *aux;
    char clave[MAX_LINEA], calif[MAX_LINEA], charEntrada[MAX_LINEA];
    char campoAux[MAX_LINEA], campoAuxDato[MAX_LINEA], razonAux[3]; 
    char stringSep[2],numIntentos[MAX_LINEA],auxNum[MAX_LINEA];
    int penultimo, i;
    long int cuantos = 0;
    contcoli = 0;
    charEntrada[0] = '\0';
    clave[0] = '\0';
    calif[0] = '\0';
    stringSep[0] = separador;
    stringSep[1] = '\0';
   
    fgets(charEntrada, MAX_LINEA, archCatalogo);
    
    while(!feof(archCatalogo))
    {
	fflush(stdin);
	fflush(stdout);
	penultimo = strlen(charEntrada)-1;
	charEntrada[penultimo]= '\0';
	//aux=new_TablaHS();
	//printf("\nCargando catalogo...");
	//printf("\ncharEntrada :%s:",charEntrada);

	i = 0;
	Busca_sep(camposLlaveCatalogo, campoAux, ',', i);

	while(campoAux[0] != '\0')
        {
	    fflush(stdin);
	    fflush(stdout);
	    Busca_sep(charEntrada, campoAuxDato, separador, atoi(campoAux));
	    strcat(clave, campoAuxDato);
	    //clave[strlen(clave)]=separador;
	    //clave[strlen(clave)]='\0';
	    strcat(clave, stringSep);
	    i++;
	    Busca_sep(camposLlaveCatalogo, campoAux, ',', i);
	}

	//printf("\nLLave :%s: ", clave);

   	i = 0;
        Busca_sep(camposCalifCatalogo, campoAux, ',', i);

	while(campoAux[0] != '\0')
        {
	    fflush(stdin);
	    fflush(stdout);
	    Busca_sep(charEntrada, campoAuxDato, separador, atoi(campoAux));
	    //strcat(aux->Calif,campoAuxDato);
	    strcat(calif, campoAuxDato);
	    i++;
	    Busca_sep(camposCalifCatalogo, campoAux, ',', i);
	}


	//printf("\nCalificador :%s: ", calif);
	Busca_sep(charEntrada,razonAux,separador,atoi(camposRazonDesc));
	razonAux[2]='\0';
	//printf("\nRazon Desconexion :%s: ",razonAux);
        //strcpy(aux->razonDesc,razonAux);
	  
	//printf("\nNum_intentos:%ld\n",num_intentos);
	Busca_sep(charEntrada,auxNum,separador,num_intentos);
	ANStrim(numIntentos,auxNum);
	ANStrim(auxNum,calif);
	//printf("numIntentos:%s-\n",numIntentos);
	//printf("Clave:%s.\n",clave);
	//printf("auxNum:%s.\n",auxNum);
	addToHash(clave,atof(auxNum),razonAux,atol(numIntentos));
	cuantos++;
	//free(charEntrada);
	//free(clave);
	//free(calif);

	charEntrada[0] = '\0';
	clave[0] = '\0';
	calif[0] = '\0';
	//aux=NULL;
	fgets(charEntrada, MAX_LINEA, archCatalogo);
   } 

   fclose(archCatalogo);

   printf("\n\nNumero de Colisiones = %ld", contcoli);
   //fprintf(archSalida,"\n El metodo Rotating Hash genero un total de %ld colisiones", contcoli);
   printf("\n\nRegistros Leidos = %ld", cuantos);
   //fprintf(archSalida,"\n\nSe agregaron %ld elementos al hashTable", cuantos);
   return TRUE;
}


//FUNCION QUE NOS SIRVE PARA TOMAR ELEMENTOS DE CADENAS SEPARADAS

void Busca_sep(char *cadent, char *cadsal, char sep, int no_cars){

    int cont_cars=0;
    int indcadent;
    int indcadsal=0;

    for (indcadent=0; cont_cars<=no_cars && cadent[indcadent]!='\0'; indcadent++)//verificamos que la cadena no este delimitada por un separador
    {
	if (cadent[indcadent] == sep) //si ya encontramos las cadena que requerimos terminamos
		      	cont_cars++;
        if (cont_cars==no_cars && cadent[indcadent]!=sep)//si no encontramos separador
	{
	     cadsal[indcadsal]=cadent[indcadent];
	     indcadsal++;
	}
    }
    cadsal[indcadsal]='\0';//ya que copiamos terminamos la cadena de salida con un nulo
}


//FUNCION QUE NOS CORTA CADENAS

void substr(char *destino, char *origen, int inicio, int final){

    int indOrigen, indDestino;

    for(indOrigen = inicio, indDestino = 0; indOrigen < final; indOrigen++, indDestino++)
    {
	 destino[indDestino] = origen[indOrigen];
    }
    destino[indDestino] = '\0';
}


//FUNCION QUE NOS BUSCA LOS ELEMENTOS EN LA TABLA Y NOS IMPRIME TODOS LOS NODOS DEL ARCHIVO DE ENTRADA

void comparaArchivoHash(){

     char aux[MAX_LINEA], charEntrada[MAX_LINEA];
     char campoAux[MAX_LINEA], campoAuxDato[MAX_LINEA];
     int penultimo, i;
     TablaHS *tofind;

     fgets(charEntrada, MAX_LINEA, archEntrada);

     while(!feof(archEntrada))
     {
	 penultimo=strlen(charEntrada)-1;
	 charEntrada[penultimo]='\0';

         i=0;
	 Busca_sep(camposLlaveEntrada, campoAux, separador, i);

	 while(campoAux[0] != '\0')
         {
             Busca_sep(charEntrada, campoAuxDato, separador, atoi(campoAux));
	     strcat(aux, campoAuxDato);
	     i++;
	     Busca_sep(camposLlaveEntrada, campoAux, separador, i);
	 }

         tofind = getkey(aux);
         if(tofind == NULL)
	     printf("\n\n<-----Elemento = %s\n\n", charEntrada);
	 else
	     printf("\n\n<-----Elemento = %s,%f\n\n", charEntrada, tofind->Calif);
	     fgets(charEntrada, MAX_LINEA, archEntrada);
	     aux[0]='\0';
     }
}


//FUNCION QUE NOS SIRVE PARA CARGAR LAS PROPIEDADES DE UN ARCHIVO DE CONFIGURACION PREDEFINIDO

int cargaPropiedades(){

    char valor[MAX_LINEA], charEntrada[MAX_LINEA];
    int opcion=0, penultimo;
    valor[0]='$';
    valor[1]='\0';
    charEntrada[0]='\0';
    HASH_SIZE=0;

    fgets(charEntrada, MAX_LINEA, archConfig);

    while (!feof(archConfig))
    {
	 penultimo=strlen(charEntrada)-1;
	 charEntrada[penultimo]='\0';
	 Busca_sep(charEntrada, valor, '=', 0);
         //printf("\ncharEntrada :%s:",charEntrada);

         if(strcmp("camposLlaveCatalogo", valor)==0)
		opcion=1;
	 else

         if(strcmp("camposCalifCatalogo", valor)==0)
		opcion=2;
	 else

         if(strcmp("camposLlaveEntrada", valor)==0)
		opcion=3;
	 else

         if(strcmp("camposCalifEntrada", valor)==0)
		opcion=4;
	 else

         if(strcmp("hashSize", valor)==0)
		opcion=5;
	 else

         if(strcmp("separador", valor)==0)
		opcion=6;
	 else

         if(strcmp("camposRazonDesc", valor)==0)
        	opcion=7;
         else

         if(strcmp("# de llamadas", valor)==0)
    	        opcion=8;
         else
       
         if(strcmp("# intentos", valor)==0)
                opcion=9;
         else
	
	 if(strcmp("filtroAreas", valor)==0)
		opcion=10;
	 else 
        
	 if(strcmp("campoFiltroAreas", valor)==0)
		opcion=11;
	
	
	 Busca_sep(charEntrada, valor, '=', 1);
         switch(opcion)
         {

              case 1:   //printf("\n camposLlaveCatalogo= :%s: ", valor);
	                strcpy(camposLlaveCatalogo, valor);
		        break;

     	      case 2:   //printf("\n camposCalifCatalogo= :%s: ", valor);
	                strcpy(camposCalifCatalogo, valor);
		        break;

	      case 3:   //printf("\n camposLlaveEntrada= :%s: ", valor);
	                strcpy(camposLlaveEntrada, valor);
			break;

              case 4:   //printf("\n camposCalifEntrada= :%s: ", valor);
		        strcpy(camposCalifEntrada, valor);
			break;

              case 5:   //printf("\n hashSize= :%s: ", valor);
		        HASH_SIZE=atol(valor);
			break;

              case 6:   //printf("\n separador= :%s: ", valor); 
	                separador=valor[0];
	                break;

              case 7:   //printf("\n camposRazonDesc = :%s: ", valor);
		        strcpy(camposRazonDesc, valor);
		        camposRazonDesc[2]='\0';
	                break;

              case 8:   //printf("\n # de llamadas = :%s: ", valor);
                        no_llamadas=atol(valor);
                 	break;

              case 9:   //printf("\n # intentos = :%s: ", valor);
         		num_intentos=atol(valor);
             	      	break;
               
	      case 10:	//printf("\n filtroAreas = :%s: ", valor);
			strcpy(filtroAreas, valor);
			break;

	      case 11:	//printf("\n campoFiltroAreas = :%s: ", valor);
			campoFiltroAreas=atol(valor);
			break;

              default:  //printf("\n Error propiedad no registrada :%s:", valor);
			  break;

	}
	charEntrada[0]='\0';
	fgets(charEntrada, MAX_LINEA, archConfig);
   }
   return TRUE;
}


//FUNCION QUE NOS SIRVE PARA TRANSFORMAR EL FORMATO QUE TRAE EL CAMPO DE DURACION DE LLAMADAS A SEGUNDOS

long int formatoToSeg(char * datos){

    char cHora[3], cMin[3], cSeg[3];
    long int liHora, liMinutos, liSeg;

    //substr(cHora, datos, 0, 2);
    cHora[0]=datos[0];
    cHora[1]=datos[1];
    cHora[2]='\0';
    liHora=atol(cHora)*3600;
    
    
    //substr(cMin, datos, 2, 4);
    cMin[0]=datos[2];
    cMin[1]=datos[3];
    cMin[2]='\0';
    liMinutos=atol(cMin)*60;
    
    
    //substr(cSeg, datos, 4, 6);
    cSeg[0]=datos[4];
    cSeg[1]=datos[5];
    cSeg[2]='\0';
    
    liSeg=atol(cSeg);
    return (liHora+liMinutos+liSeg);

}


//FUNCION QUE TRANSFORMA LOS SEGUNDOS ACUMULADOS AL FORMATO DEL CAMPO DE DURACION DE LLAMADAS

void segToFormato(char *destino, long int segundosTotales){

    fflush(stdin);
    char cHora[2],cMin[2],cSeg[2],aux[2],total[7];
    int liHora,liMinutos,liSeg;
    //1001935
    liHora = segundosTotales/3600;

    if(liHora < 10)
    {
        sprintf(aux,"%d",liHora);
	//ltoa(liHora,aux,10);
	//strcpy(cHora,"0");
	//strcat(cHora,aux);
        cHora[0]='0';
        cHora[1]=aux[0];
        
    }
    else
    {
        sprintf(aux,"%d",liHora);
	//ltoa(liHora,aux,10);
	//strcpy(cHora,aux);
	cHora[0]=aux[0];
	cHora[1]=aux[1];
	    
    }

    //strcpy(total,cHora);
    //printf("\n%s",cHora);

    liMinutos = (segundosTotales%3600)/60;

    if(liMinutos < 10)
    {
       sprintf(aux,"%d",liMinutos);
       //ltoa(liMinutos,aux,10);
       //strcpy(cMin,"0");
       //strcat(cMin,aux);
       cMin[0]='0';
       cMin[1]=aux[0];
    }
    else
    {
        sprintf(aux,"%d",liMinutos);
        //ltoa(liMinutos,aux,10);
        //strcpy(cMin,aux);
        cMin[0]=aux[0];
        cMin[1]=aux[1];
    }

    //strcat(total,cMin);
    //printf("\n%s",cMin);

    liSeg = (segundosTotales%3600)%60;

    if(liSeg < 10)
    {
	sprintf(aux,"%d",liSeg);
	//ltoa(liSeg,aux,10);
	//strcpy(cSeg,"0");
	//strcat(cSeg,aux);
	cSeg[0]='0';
	cSeg[1]=aux[0];
    }
    else
    {
	sprintf(aux,"%d",liSeg);
	//ltoa(liSeg,aux,10);
	//strcpy(cSeg,aux);
	cSeg[0]=aux[0];
	cSeg[1]=aux[1];
    }

    strcat(total,cSeg);
    //printf("\n%s",cSeg);
    total[0]=cHora[0];
    total[1]=cHora[1];
    total[2]=cMin[0];
    total[3]=cMin[1];
    total[4]=cSeg[0];
    total[5]=cSeg[1];
    total[6]='\0';
    strcpy(destino,total);

}


//FUNCION QUE NOS VALIDA QUE LAS FECHAS SEAN CORRECTAS
// Espera fechas con el formato aammdd, retorna 1 si esta correcta, 0 si no

int valida_fecha(char fecha_proceso[])
{
   char anio[5]={""}, mes[5]={""}, dia[5]={""};
   int status=1, max_dia=0, n_anio=0, n_mes=0;

   substr(anio, fecha_proceso, 0, 2);
   substr(mes, fecha_proceso, 2, 4);
   substr(dia, fecha_proceso, 4, 6);

   //printf("\n\nanio:%s\n",anio);
   //printf("mes:%s\n",mes);
   //printf("dia:%s\n",dia);
   //getchar();

   if(atoi(anio)<0)
     status=0;
   else
   {
      n_anio=atoi(anio)+2000;
      if(atoi(mes)<=0 || atoi(mes)>12)
        status=0;
      else
      {
         n_mes=atoi(mes);
         if(n_mes==1||n_mes==3||n_mes==5||n_mes==7||n_mes==8||n_mes==10||n_mes==12)
            max_dia=31;
         else
         {
            if(n_mes==2)
            {
               if((n_anio%4)==0)
                 max_dia=29;
               else
                 max_dia=28;
            }
            else
               max_dia=30;
         }

         if(atoi(dia)<=0 || atoi(dia)>max_dia)
           status=0;
      }
   }
   return(status);
}


//FUNCION QUE NOS COMPARA LAS DIFERENTES RAZONES DE DESCONEXION PARA SELECCIONAR
//Y ASI PODER PROCESAR LA RAZON QUE NOS VAYA LLEGANDO Y ACUMULARLA DE MANERA ADECUADA

int selectRadex(double duracion, char *razon){

    //(if (duracion != 0)
    if (duracion > 0)
		return 0;
    else

    if (strcmp("00", razon)==0 || strcmp("09", razon)==0)
		return 0;
    else

    if (strcmp("FF", razon)==0)
		return 1;
    else

    if (strcmp("0F", razon)==0 || strcmp("0A", razon)==0)
		return 2;
    else

    if (strcmp("05", razon)==0)
		return 3;
    else

    if (strcmp("03", razon)==0)
		return 4;
    else

    if (strcmp("04", razon)==0)
		return 5;
    else

    if (strcmp("06", razon)==0)
		return 6;
    else

    if (strcmp("07", razon)==0)
		return 7;
    else

    if (strcmp("01", razon)==0)
		return 8;
    else

    if (strcmp("0B", razon)==0)
		return 9;
    else

    if (strcmp("08", razon)==0)
		return 10;
    else

    if (strcmp("0C", razon)==0)
		return 11;
    else

    if (strcmp("02", razon)==0)
		return 12;
    else
		return 13;
}


//FUNCION QUE NOS IMPRIME LA SALIDA DE LOS CAMPOS ACUMULADOS CON SUS RESPECTIVAS RAZONES DE DESCONEXION

void imprimeIntentos(){

     int i,j,k;
     TablaHS *aux;
     char *campoAux;
     long int cuantos = 0;
     long int suminttot = 0;

     for (i=0; i<HASH_SIZE; i++)
     {
	  aux = TABLAHASH[i];
	  while (aux != NULL)
          {
	       if(seleccionadorFiltroArea(aux->Clave))
	       {
	          if(aux->contLlam >= no_llamadas)//Filtro para largas distancias o locales
	          {
		      campoAux = (char *) malloc (sizeof(char) * strlen(aux->Clave)+1);
		      if(campoAux == NULL)
		      {
			  printf("\n No hay suficiente memoria ");
				   cleanupHash();
				  exit(1);
		      }
		      campoAux[0]=NULL;
		      //campoAux[strlen(campoAux)-1] = '\0';
		         
		      for(j=0; j<strlen(aux->Clave); j++)
		      {
			  if(aux->Clave[j]==separador)  
                               campoAux[j]=',';
                          else
			       campoAux[j]=aux->Clave[j];
		      }
		      campoAux[j]='\0';
		      fprintf(archSalida,"%s",campoAux);
		      //printf("%s",campoAux);
		      free(campoAux); 
			  
	              fprintf(archSalida,"%ld,",aux->contLlam); 
		      //printf("%ld,",aux->contLlam);

	 	      for(k=0;k<14;k++)
		      {
		    	  if(aux->razonDescon[k]==0)
		  	      fprintf(archSalida,"0,");
			      //printf(",");
		  	  else
		  	      fprintf(archSalida,"%ld,",aux->razonDescon[k]);
			      //printf("%ld,",aux->razonDescon[k]);
		      }	
		  	        
		      fprintf(archSalida,"%6.2f,",aux->Calif);
		      fprintf(archSalida,"%s\n",fecha_proceso);
		      //printf("%s\n",fecha_proceso);
		      //printf("%f\n",aux->Calif);
                  }
	       }
	       suminttot+=aux->contLlam;
	       cuantos++;
	       aux = aux->sig;
          }
     }
     printf("\nRegistros Escritos = %ld", cuantos);
     printf("\nIntentos Totales = %ld", suminttot);
}


//FUNCION QUE NOS MUESTRA COMO SE LE ASIGNAN LOS LUGARES A LAS CLAVES POR CADA UNO DE LOS NODOS DE LA TABLA HASH

void imprimeHash(){

    int i=0;
    TablaHS *aux;

    for(i=0; i<HASH_SIZE; i++)
    {
        aux = TABLAHASH[i];
	printf("\n Clave[%d]: ", i);
	while(aux != NULL)
        {
	    printf(" %s ,", aux->Clave);
	    aux = aux->sig;
	}
    }
}


//FUNCION QUE NOS MUESTRA LA SALIDA DE LA SUMA DE LOS MINUTOS Y EL CONTEO DE LLAMADAS DEL ARCHIVO DE ENTRADA

void imprimeSumaCont(){

    int i=0;
    TablaHS *aux;

    for(i=0; i<HASH_SIZE; i++)
    {
        aux = TABLAHASH[i];
        //printf("\n  ",i);
        while(aux != NULL)
        {
	    printf("\n %s %f %ld,", aux->Clave, aux->Calif, aux->contLlam);
	    aux = aux->sig;
        }
    }
}


//FUNCION QUE NOS LIBERA LA MEMORIA

//void cleanupHash(int modo)
void cleanupHash()
{
    int i;
    TablaHS *aux,*t;
    for(i=0; i<HASH_SIZE; i++)
    {
        if(TABLAHASH[i] != NULL)
        {
	     aux=TABLAHASH[i];
	     while(aux != NULL)
	     {
	         t=aux->sig;
	         free(aux->Clave);
	         aux->Calif=0;
	         free(aux);
	         aux=t;
	     }
        }
    }
    free(TABLAHASH);

/******   
   if( modo==99 )
      printf ("\n !> Error No hay memoria disponible para ejecutar el proceso\n",0,RazonDesconexion);

   else

   if( modo==SIGTSTP || modo==SIGSTOP )
      Error("El proceso ha sido detenido. Se libera la memoria\n",1,RazonDesconexion);

   else

   if( modo==SIGINT )
      Error("El proceso ha sido interrumpido. Se libera la memoria\n",1,RazonDesconexion);

   else

   if( modo==98 )
      Error("Desborde en la tabla de registros. Se libera la memoria\n",1,RazonDesconexion);
*****/
}

void ANStrim(char *destino, char * origen){
        int i,j;
	
        for (i=0,j=0;i<strlen(origen);i++){
	if(isalnum(origen[i]) || origen[i]=='.'){
	//if(isalnum(origen[i]) == 4 || origen[i]=='.'){
	          destino[j]=origen[i];
		j++;
	}
       }
       destino[j]='\0';
       //destino[strlen(destino)]='\0';
}

//FUNCION QUE NOS BUSCA INFORMACION PARA PODER REALIZAR UN FILTRO PARA UNA SALIDA ESPECIFICA DE ALL ESPEC

int seleccionadorFiltroArea(char *key ){

   char filtro[MAX_LINEA],lista[MAX_LINEA];
   long int i=0;
   //lista[0]='';
   //printf("\nel filtro es el campo num %ld  ",campoFiltroAreas);
   Busca_sep(key, filtro, separador, campoFiltroAreas);
   //printf("\nel filtro es el campo :%s:\n",filtro);
   Busca_sep(filtroAreas, lista, ',', i);

   while(lista[0] != '\0')
   {
      //printf("\ncomparando :%s: con :%s:\n",lista,filtro);
      if(strcmp(lista,filtro)==0)
	    return 1;
      i++;
      Busca_sep(filtroAreas, lista, ',', i);
   }
   return 0;
}

#endif
